<script setup lang="ts">
import { ElMessageBox } from 'element-plus'
import { useRouter } from 'vue-router'
import { useGame } from '@/views/game2048/hooks/game'
import type { direction } from '@/views/game2048/types'

const { board, score, move, restart } = useGame()

const isGameOver = ref(false) // 游戏是否结束状态
const isAlertShowing = ref(false) // 防止重复弹窗标志
const router = useRouter()

let touchStartX = 0
let touchStartY = 0

// 触摸开始记录坐标，用于计算滑动方向
function onTouchStart(e: TouchEvent) {
  touchStartX = e.touches[0].clientX
  touchStartY = e.touches[0].clientY
}

// 触摸结束计算滑动方向，触发对应移动
function onTouchEnd(e: TouchEvent) {
  const deltaX = e.changedTouches[0].clientX - touchStartX
  const deltaY = e.changedTouches[0].clientY - touchStartY

  if (Math.abs(deltaX) > Math.abs(deltaY)) {
    moveWithCheck(deltaX > 0 ? 'right' : 'left')
  }
  else {
    moveWithCheck(deltaY > 0 ? 'down' : 'up')
  }
}

// 重新开始游戏，重置状态
function restartGame() {
  restart()
  isGameOver.value = false
}

// 包装移动操作，加入分数更新和游戏结束检测
function moveWithCheck(dir: direction) {
  if (isGameOver.value)
    return // 游戏结束后不响应操作

  const gained = move(dir)
  if (gained > 0) {
    score.value += gained
  }

  checkGameOver()
}

// 检测游戏是否结束：无空格且无可合并块时结束
function checkGameOver() {
  if (isAlertShowing.value)
    return // 弹窗显示时不重复检测弹窗

  const flat = board.value.flat()
  if (flat.includes(0))
    return // 存在空格不结束

  // 检查是否还有相邻可合并的方块
  const canMerge = () => {
    for (let i = 0; i < 4; i++) {
      for (let j = 0; j < 4; j++) {
        const val = board.value[i][j]
        if (j < 3 && val === board.value[i][j + 1])
          return true
        if (i < 3 && val === board.value[i + 1][j])
          return true
      }
    }
    return false
  }

  if (!canMerge()) {
    isGameOver.value = true
    isAlertShowing.value = true
    ElMessageBox.alert(
      `游戏结束！您的得分为 ${score.value} 分。`,
      '提示',
      {
        confirmButtonText: '重新开始',
        cancelButtonText: '返回首页',
        showCancelButton: true,
      },
    )
      .then(() => {
        // 点击“重新开始”按钮
        isAlertShowing.value = false
        restartGame()
      })
      .catch(() => {
        // 点击“返回首页”按钮或关闭弹窗
        isAlertShowing.value = false
        router.push('/')
      })
  }
}
// 支持方向键和WASD控制
function handleKeydown(e: KeyboardEvent) {
  const keyMap: Record<string, string> = {
    ArrowUp: 'up',
    ArrowDown: 'down',
    ArrowLeft: 'left',
    ArrowRight: 'right',
    w: 'up',
    s: 'down',
    a: 'left',
    d: 'right',
    W: 'up',
    S: 'down',
    A: 'left',
    D: 'right',
  }
  const direction = keyMap[e.key]
  if (direction) {
    moveWithCheck(direction)
  }
}

onMounted(() => {
  window.addEventListener('keydown', handleKeydown)
  // 组件卸载时移除事件监听，防止内存泄漏
  onBeforeUnmount(() => {
    window.removeEventListener('keydown', handleKeydown)
  })
})
function handleRouter() {
  router.push('/')
}
</script>

<template>
  <div class="game-container" @touchstart="onTouchStart" @touchend="onTouchEnd">
    <div class="header">
      <h1>2048 游戏</h1>
    </div>
    <div class="operation">
      <div>得分：{{ score }}</div>
      <div class="button">
        <el-button type="primary" @click="restartGame">
          重新开始
        </el-button>
        <el-button @click="handleRouter">
          返回首页
        </el-button>
      </div>
    </div>
    <div class="grid">
      <div v-for="(row, rowIndex) in board" :key="rowIndex" class="row">
        <div
          v-for="(cell, cellIndex) in row"
          :key="cellIndex"
          class="cell"
          :class="`cell-${cell}`"
        >
          {{ cell || '' }}
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
$cell-text-color: #776e65;
$cell-radius: 4px;

$cell-colors: (
  2: #eee4da,
  4: #ede0c8,
  8: #f2b179,
  16: #f59563,
  32: #f67c5f,
  64: #f65e3b,
  128: #edcf72,
  256: #edcc61,
  512: #edc850,
  1024: #edc53f,
  2048: #edc22e,
);

.game-container {
  max-width: 320px;
  margin: 1em auto;
  user-select: none;
  .header {
    display: flex;
    justify-content: center;
    align-items: center;
    margin-bottom: 10px;
    h1 {
      font-weight: bold;
      font-size: 1.5rem;
    }
  }
  .operation {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
    font-size: 1.5rem;
  }
  .grid {
    background: #bbada0;
    border-radius: 8px;
    padding: 8px;
    .row {
      display: flex;
      .cell {
        width: 72px;
        height: 72px;
        margin: 4px;
        border-radius: $cell-radius;
        background-color: #cdc1b4;
        font-weight: bold;
        font-size: 1.8rem;
        color: $cell-text-color;
        display: flex;
        justify-content: center;
        align-items: center;
        &.cell-0 {
          background-color: #cdc1b4;
          color: transparent;
        }
        @each $num, $color in $cell-colors {
          &.cell-#{$num} {
            background-color: $color;
            color: if($num > 4, white, $cell-text-color);
          }
        }
      }
    }
  }
}
</style>
